#ifndef __ARK_BLOCKING_QUEUE_H__
#define __ARK_BLOCKING_QUEUE_H__

#include <list>
#include <mutex>
#include <memory>
#include <functional>

namespace Ark
{
    class BlockingQueue
    {
    public:
        struct Task {
            void* userdata = nullptr;
            std::function<void()> task;

            Task();
            Task(const std::function<void()>& task);
            Task(const std::function<void()>&& task);
        };
        typedef std::shared_ptr<Task> TaskPtr;
        enum {
            WAIT_INFINITE = -1
        };
    public:
        BlockingQueue();
        ~BlockingQueue();
        BlockingQueue(const BlockingQueue&) = delete;
        void operator = (const BlockingQueue&) = delete;

    public:
        void Push(TaskPtr task);
        TaskPtr Pop(int waitSeconds = WAIT_INFINITE);
        bool IsEmpty();

    private:
        std::mutex _mutex;
        std::condition_variable _cond;
        std::list<TaskPtr> _taskList;
        unsigned _waitCount = 0;
    };
}

#endif  //__ARK_BLOCKING_QUEUE_H__
